package stream.method;

import stream.BookCase;
import stream.StreamsLearn;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @CreateBy zhangdingyi
 * @Date 2022-10-07
 * @Content 其他流的转换 与 简单约简
 */
public class Three {
    public static void main(String[] args) {
        testDistinct();
        //testSorted();
        //testPeek();
        //testFindData();

    }

    /**
     * 这个是剔除重复的数据
     * 产生一个流，包含当前流中所有不同的元素
     */
    static void testDistinct() {
        //注意这里仅能对 流进行一次操作 --就是 StreamsLearn.show("sream",sream); 使用了之后
        //下一个show就会报错 stream has already been operated upon or closed
        Stream<String> sream = Stream.of("Hello, world", "Hello, world", "Hello, world", "Helloworld", "HelloWorld", "HelloWorld", "HelloWorld2");
        //StreamsLearn.show("sream",sream);
        //这个去重挺好使的 -直接把一样的数据给除掉了，那么对象集合是否会一并去重？
        Stream<String> distinct = sream.distinct();
        StreamsLearn.show("sream-Distinct", distinct);

        //对象集合去重 --distinct 对于多个字段不会生效
        List<BookCase> listObjRepeat = StreamsLearn.getListObjRepeat();
        List<BookCase> bookCaseStream = listObjRepeat.stream().distinct().collect(Collectors.toList());

        for (BookCase bookCase : bookCaseStream) {
            System.out.println("bookCase -> id -> " + bookCase.getId() + ",name -> " + bookCase.getName() + ",uuid -> " + bookCase.getUuid());
        }
        List<String> distinctName = listObjRepeat.stream().map(BookCase::getName).distinct().collect(Collectors.toList());
        for (String name : distinctName) {
            System.out.println("distinctName -> name -> " + name);
        }

    }

    /**
     * 给 流的内容进行排序
     * 产生一个流，它的元素是当前流中的所有元素按照顺序排列的。sorted方法要求元素是实现了Comparable的类的实例。
     */
    static void testSorted() {
        Stream<String> sream = Stream.of("z", "zx", "zxc", "zxca", "z", "zxcdq", "HelloWorld2", "13adaw");
        //使得最长的字符串排序在前面
        Stream<String> sorted = sream.sorted(Comparator.comparing(String::length).reversed());
        StreamsLearn.show("sorted", sorted);
    }

    /**
     * peek 的使用，简单的说这个东西就是 对每个数据进行一次处理,但仅是对值进行处理，不会反馈至原数据
     * 产生一个流，它与当前流中的元素相同，在获取其中每个元素时，会将其传递给action。
     * <p>
     * 那么在这里看，这个东西与 foreach 有什么不同呢？
     * foreach 方法 是对集合进行 遍历操作 --操作完了就把流 给关掉了
     * peek 方法 也是对集合进行 遍历操作 --操作完了还会返回一个 流
     * <p>
     * 简单约简
     * max 和 min 方法
     * 分别产生这个流的最大元素和最小元素，使用由给定比较器定义的排序规则，如果这个流为空，会产生一个空的Optional对象。这些操作都是终结操作。
     */
    static void testPeek() {
        //这里得出的结果都是 1.0 * 2，2.0 * 2，4.0 * 2 以此类推
        Object[] objects = Stream.iterate(1.0, p -> p * 2)
                .peek(e -> System.out.println("peek e -> " + (e = e + 0.1)))
                .limit(20).toArray();
        //在peek 中处理数据，现在重新遍历值不会改变
        Arrays.stream(objects).forEach(object -> System.out.println("peek object -> " + object));
        Stream<Double> sream = Stream.of(1.0, 2.0, 3.0, 4.0, 5.0);
        //获取最值 -这个也是终止 流的方法
        //分别产生这个流的最大元素和最小元素，使用由给定比较器定义的排序规则，如果这个流为空，会产生一个空的Optional对象。这些操作都是终结操作。
        Optional<Double> max = sream.max(Double::compareTo);
        System.out.println("max: " + max.orElse(1d));
        //forEach 这里是直接结束流的操作
        //sream.forEach(e -> System.out.println("forEach e1 -> " + (e = e + 0.1)));

        //这里流结束了，再对流继续执行就会报错 stream has already been operated upon or closed
        //sream.forEach(e -> System.out.println("forEach e2 -> " + e));
        //这里哪怕是 中间方法 peek 使用起来也是蛮难的
        //System.out.println(sream.peek(e -> System.out.println("peek e2 -> " + e)));


    }

    /**
     * 简单约简 从流数据中获得答案 -约简是一种终结操作（terminal operation），它们会将流约简为可以在程序中使用的非流值。
     * <p>
     * 这里是直接 找到对应数据的值
     * <p>
     * findFirs、findAny
     * 分别产生这个流的第一个和任意一个元素，如果这个流为空，会产生一个空的Optional对象。这些操作都是终结操作
     * <p>
     * anyMatch、allMatch、noneMatch
     * 分别在这个流中任意元素、所有元素和没有任何元素匹配给定断言时返回true。这些操作都是终结操作
     */
    static void testFindData() {
        Stream<String> sream = Stream.of("Hello, world", "Hello, world", "Hello, world", "Helloworld", "HelloWorld", "HelloWorld", "HelloWorld2");
        System.out.println("HelloWorld2".indexOf("3"));
        //这里是直接对所有的数据进行查找，如果有一样的就输出 但仅输出一个
        //Optional<String> any = sream.filter(s -> s.indexOf("2") != -1 ? true : false).findAny();
        //Optional<String> any = sream.filter(s -> s.indexOf("Hello") != -1 ? true : false).findAny();
        //System.out.println(any.orElse("123"));

        //anyMatch 是对于所有是数据进行匹配 如果有就返回 true
        boolean hello = sream.anyMatch(s -> s.indexOf("3") != -1 ? true : false);
        System.out.println(hello);
    }

}
